Base table
A simplified table component for displaying structured data in a clean, accessible format.
#Table vs. Base Table
Component | Purpose | Usage |
---|---|---|
Table | A feature-rich table component optimized for complex data interactions. Offers sorting, filtering, pagination, row selection, etc. | Displaying extensive datasets requiring user manipulation. |
Base table | A streamlined table for presenting structured data without advanced interactions. | Displaying smaller datasets within dashboards or cards where complex interactions are not the primary focus. |
#Examples
#Basic usage
This will render a basic table with headers and data cells.
Header |
---|
foo |
bar |
<BaseTable
items={[{ text: "foo" }, { text: "bar" }]}
columns={[{ header: "Header", render: (item) => <div>{item.text}</div> }]}
withoutKeyColumn
/>
#With caption
The caption provides a brief description of the table's content, aiding screen reader users and improving overall comprehension.
Header |
---|
foo |
bar |
<BaseTable
items={[{ text: "foo" }, { text: "bar" }]}
columns={[{ header: "Header", render: (item) => <div>{item.text}</div> }]}
caption="Caption for table"
withoutKeyColumn
/>
#Expandable cells
Enable users to delve deeper into specific data points by making cells expandable. This allows for the display of additional details or actions within the cell.
Columns can be marked expandable.isExpandable
is a function that gets called for each cell so you can control exactly which ones are expandable.
Header |
---|
foo |
<BaseTable
items={[
{ text: "foo", count: 0 },
{ text: "bar", count: 1 },
]}
columns={[
{
header: "Header",
render: (item) => <div>{item.text}</div>,
isExpandable: (item) => item.count > 0,
},
]}
withoutKeyColumn
/>
#With row highlight
Visually emphasize specific rows based on certain criteria.
You can do so by providing a function as highlightRow
prop which takes an item as parameter and returns a boolean which indicates whether or not to highlight an item. This function gets called for each row and adds a highlight class to those matching the criteria.
Header | Count |
---|---|
foo | 0 |
bar | 1 |
<BaseTable
items={[
{ text: "foo", count: 0 },
{ text: "bar", count: 1 },
]}
columns={[
{ header: "Header", render: (item) => <div>{item.text}</div>, isKeyColumn: true },
{ header: "Count", render: (item) => <div>{item.count}</div> },
]}
highlightRow={(item) => item.text === "foo"}
/>
#With column summary
You can also display an extra row in the table header that contains the summary of a corresponding column. The summary content is formed by a number value and a label. The number value can also be provided as a string, enabling the use of number formatters. To display the summary of a column, use the property summary
in the specifications of a column, as exemplified below.
Header | Count |
---|---|
1 total | |
foo | 0 |
bar | 1 |
<BaseTable
items={[
{ text: "foo", count: 0 },
{ text: "bar", count: 1 },
]}
columns={[
{ header: "Header", render: (item) => <div>{item.text}</div>, isKeyColumn: true },
{
header: "Count",
render: (item) => <div>{item.count}</div>,
summary: {
value: 1,
label: "total",
},
},
]}
/>
#Keeping state
You might've noticed in the Expandable cells example that nothing happens when clicking the expander. Why? Because BaseTable
is stateless. It's not its concern to know what's expanded, only to render that it is expandable. Lets hook it up so expanding works. In the below example note how we keep track of state ourselves, and push that state into BaseTable so it always renders the right thing.
Header |
---|
const [state, setState] = useState<BaseTableCellPosition>();
return (
<BaseTable
items={[{ text: "foo" }, { text: "bar" }]}
columns={[
{
header: "Header",
render: (item) => <div>{item.text}</div>,
isExpandable: () => true,
},
]}
withoutKeyColumn
expandedContentRenderer={() => <div>I 💓 expanded content</div>}
expandedCellPosition={state}
onExpandClick={(e, cellPosition) => {
// If the user clicks an already-expanded cell we want to collapse, i.e. reset state
if (
state &&
state.columnNum == cellPosition.columnNum &&
state.rowNum == cellPosition.rowNum
) {
setState(undefined);
return;
}
setState(cellPosition);
}}
/>
);
#Loading state
When fetching data, provide a visual indicator (e.g. Spinner) to inform the user that the table is loading.
Header | Count |
---|---|
Loading items |
<BaseTable<{ text: string; count: number }>
loading={true}
loadingText="Loading items"
items={[]}
columns={[
{ header: "Header", render: (item) => <div>{item.text}</div>, isKeyColumn: true },
{ header: "Count", render: (item) => <div>{item.count}</div> },
]}
/>
#No data state
When no data is available, display a clear, informative message ( e.g. "Accessibility issues have been resolved."). Consider the context and provide guidance on how to resolve the issue if possible.
The noDataState
is used to indicate that no data is available for display. An Empty State component with the type
"reassure" and default heading is shown, but it can be overridden by another type with custom text. For guidelines please refer to the Empty State component.
Header | Count |
---|---|
No data to display |
<BaseTable<{ text: string; count: number }>
items={[]}
columns={[
{ header: "Header", render: (item) => <div>{item.text}</div>, isKeyColumn: true },
{ header: "Count", render: (item) => <div>{item.count}</div> },
]}
/>
#Properties
Header 1 | Header 2 |
---|---|
foo | bar |
bar | foo |
Property | Description | Defined | Value |
---|---|---|---|
columnsRequired | object[] Column configurations | ||
itemsRequired | unknown[] Items to be displayed | ||
onExpandClickOptional | function Callback for when expander is clicked | ||
expandedContentRendererOptional | function Renderer for content of expanded cell | ||
expandedCellPositionOptional | object Position of the expanded cell | ||
element Footer displayed below table data | |||
topAlignedOptional | boolean Is the content top aligned? | ||
highlightRowOptional | function Compare function for highlight row | ||
rowKeyOptional | function Function to generate a key for rows | ||
string Caption for the table | |||
withoutKeyColumnOptional | boolean Does this table not have a key column? Be sure this is the case otherwise the table is less accessible | ||
thClassNameOptional | string ClassName for th elements | ||
trClassNameOptional | string ClassName for tr elements | ||
tdClassNameOptional | string ClassName for td elements | ||
loadingOptional | boolean Is the table in a loading state? | ||
loadingTextOptional | string Optional text to be displayed when the table is loading | ||
noDataStateOptional | element Content to be shown when there's no data. An Empty State component is shown by default, but it can be overridden by another type with custom text. | ||
data-componentOptional | string Name of the component. Should only be set by components since it needs to stable. Used to track component usage | ||
data-observe-keyOptional | string Unique string, used by external script e.g. for event tracking | ||
classNameOptional | string Custom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | object Style object to apply custom inline styles (only intended for special cases) |
#Guidelines
#Best practices
#Do not use when
#Accessibility
Explore detailed guidelines for this component: Accessibility Specifications